1 /*
2  * Copyright (c) 2011-2014 - Mauro Carvalho Chehab
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation version 2.1 of the License.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; if not, write to the Free Software
15  */
16 
17 module libdvbv5_d.dvb_file;
18 
19 import core.stdc.stdlib: free;
20 
21 import libdvbv5_d.dvb_fe: dvb_v5_fe_parms;
22 import libdvbv5_d.dvb_frontend: DTV_MAX_COMMAND, dtv_property;
23 import libdvbv5_d.dvb_scan:  dvb_v5_descriptors;
24 
25 extern (C):
26 
27 /**
28  * @file dvb-file.h
29  * @ingroup file
30  * @brief Provides interfaces to deal with DVB channel and program files.
31  * @copyright GNU Lesser General Public License version 2.1 (LGPLv2.1)
32  * @author Mauro Carvalho Chehab
33  *
34  * There are basically two types of files used for DVB:
35  * - files that describe the physical channels (also called as transponders);
36  * - files that describe the several programs found on a MPEG-TS (also called
37  *   as zap files).
38  *
39  * The libdvbv5 library defines an unified type for both types. Other
40  * applications generally use different formats.
41  *
42  * The purpose of the functions and structures defined herein is to provide
43  * support to read and write to those different formats.
44  *
45  * @par Bug Report
46  * Please submit bug reports and patches to linux-media@vger.kernel.org
47  */
48 
49 /*
50  * DVB structures used to represent all files opened by the libdvbv5 library.
51  *
52  * Those structs represents each individual entry on a file, and the file
53  * as a whole.
54  */
55 
56 /**
57  * @struct dvb_elementary_pid
58  * @brief associates an elementary stream type with its PID
59  * @ingroup file
60  *
61  * @param type	Elementary stream type
62  * @param pid	Elementary stream Program ID
63  */
64 struct dvb_elementary_pid
65 {
66     ubyte type;
67     ushort pid;
68 }
69 
70 /**
71  * @struct dvb_entry
72  * @brief  Represents one entry on a DTV file
73  * @ingroup file
74  *
75  * @param props			A property key/value pair. The keys are the ones
76  *				specified at the DVB API, plus the ones defined
77  *				internally by libdvbv5, at the dvb-v5-std.h
78  *				header file.
79  * @param next			a pointer to the next entry. NULL if this is
80  *				the last one.
81  * @param service_id		Service ID associated with a program inside a
82  *				transponder. Please note that pure "channel"
83  *				files will have this field filled with 0.
84  * @param video_pid		Array with the video program IDs inside a service
85  * @param audio_pid		Array with the audio program IDs inside a service
86  * @param other_el_pid		Array with all non-audio/video  program IDs
87  *				inside a service
88  * @param video_pid_len		Size of the video_pid array
89  * @param audio_pid_len		Size of the audio_pid array
90  * @param other_el_pid_len	Size of the other_el_pid array
91  * @param channel		String containing the name of the channel
92  * @param vchannel		String representing the Number of the channel
93  * @param location		String representing the location of the channel
94  * @param sat_number		For satellite streams, this represents the
95  *				number of the satellite dish on a DiSeqC
96  *				arrangement. Should be zero on arrangements
97  *				without DiSeqC.
98  * @param freq_bpf		SCR/Unicable band-pass filter frequency to
99  *				use, in kHz.
100  *				For non SRC/Unicable arrangements, it should
101  *				be zero.
102  * @param diseqc_wait		Extra time to wait for DiSeqC commands to
103  *				complete, in ms. The library will use 15 ms
104  *				as the minimal time,
105  *				plus the time specified on this field.
106  * @param lnb			String with the name of the LNBf to be used for
107  *				satellite tuning. The names should match the
108  *				names provided by dvb_sat_get_lnb() call
109  *				(see dvb-sat.h).
110  */
111 struct dvb_entry
112 {
113     dtv_property[DTV_MAX_COMMAND] props;
114     uint n_props;
115     dvb_entry* next;
116     ushort service_id;
117     ushort* video_pid;
118     ushort* audio_pid;
119     dvb_elementary_pid* other_el_pid;
120     uint video_pid_len;
121     uint audio_pid_len;
122     uint other_el_pid_len;
123     char* channel;
124     char* vchannel;
125 
126     char* location;
127 
128     int sat_number;
129     uint freq_bpf;
130     uint diseqc_wait;
131     char* lnb;
132 
133     ushort network_id;
134     ushort transport_id;
135 }
136 
137 /**
138  * @struct dvb_file
139  * @brief  Describes an entire DVB file opened
140  *
141  * @param fname		name of the file
142  * @param n_entries	number of the entries read
143  * @param first_entry	entry for the first entry. NULL if the file is empty.
144  */
145 struct dvb_file
146 {
147     char* fname;
148     int n_entries;
149     dvb_entry* first_entry;
150 }
151 
152 /*
153  * DVB file format tables
154  *
155  * The structs below are used to represent oneline formats like the ones
156  * commonly found on DVB legacy applications.
157  */
158 
159 /**
160  * @struct dvb_parse_table
161  * @brief  Describes the fields to parse on a file
162  * @ingroup file
163  *
164  * @param prop			Name of the DVBv5 or libdvbv5 property field
165  * @param table			Name of a translation table for string to
166  *				int conversion
167  * @param size			Size of the translation table
168  * @param mult_factor		Multiply factor - Used, for example, to
169  *				multiply the symbol rate read from a DVB-S
170  *				table by 1000.
171  * @param has_default_value	It is different than zero when the property
172  *				can be optional. In this case, the next field
173  *				should be present
174  * @param default_value		Default value for the optional field
175  */
176 struct dvb_parse_table
177 {
178     uint prop;
179     const(char*)* table;
180     uint size;
181     int mult_factor;
182     int has_default_value;
183     int default_value;
184 }
185 
186 /**
187  * @struct dvb_parse_struct
188  * @brief  Describes the format to parse an specific delivery system
189  * @ingroup file
190  *
191  * @param id		String that identifies the delivery system on the
192  * 			file to be parsed
193  * @param delsys	Delivery system
194  * @param table		the struct dvb_parse_table used to parse for this
195  *			specific delivery system
196  * @param size		Size of the table
197  */
198 struct dvb_parse_struct
199 {
200     char* id;
201     uint delsys;
202     const(dvb_parse_table)* table;
203     uint size;
204 }
205 
206 /**
207  * @struct dvb_parse_file
208  * @brief  Describes an entire file format
209  *
210  * @param has_delsys_id		A non-zero value indicates that the id field
211  *				at the formats vector should be used
212  * @param delimiter		Delimiters to split entries on the format
213  * @param formats		A struct dvb_parse_struct vector with the
214  *				per delivery system parsers. This table should
215  *				terminate with an empty entry.
216  */
217 struct dvb_parse_file
218 {
219     int has_delsys_id;
220     char* delimiter;
221     dvb_parse_struct[] formats;
222 }
223 
224 /**
225  * @enum  dvb_file_formats
226  * @brief Known file formats
227  * @ingroup file
228  *
229  * @details
230  * Please notice that the channel format defined here has a few optional
231  * fields that aren't part of the dvb-apps format, for DVB-S2 and for DVB-T2.
232  * They're there to match the formats found at dtv-scan-tables package up to
233  * September, 5 2014.
234  *
235  * @var FILE_UNKNOWN
236  *	@brief File format is unknown
237  * @var FILE_ZAP
238  *	@brief File is at the dvb-apps "dvbzap" format
239  * @var FILE_CHANNEL
240  *	@brief File is at the dvb-apps output format for dvb-zap
241  * @var FILE_DVBV5
242  *	@brief File is at libdvbv5 format
243  * @var FILE_VDR
244  *	@brief File is at DVR format (as supported on version 2.1.6).
245  *	       Note: this is only supported as an output format.
246  */
247 enum dvb_file_formats
248 {
249     FILE_UNKNOWN = 0,
250     FILE_ZAP = 1,
251     FILE_CHANNEL = 2,
252     FILE_DVBV5 = 3,
253     FILE_VDR = 4
254 }
255 
256 // struct dvb_v5_descriptors;
257 
258 /**
259  * @brief Deallocates memory associated with a struct dvb_file
260  * @ingroup file
261  *
262  * @param dvb_file	dvb_file struct to be deallocated
263  *
264  * This function assumes that several functions were dynamically allocated
265  * by the library file functions.
266  */
267 
268 // DStep produces:
269 //
270 //void dvb_file_free (dvb_file* dvb_file);
271 //
272 // for this but it is an inline function with no symbol in the libdvbv5.so shared object.
273 // An implementation must be provided, this is a translation from C to D.
274 
275 void dvb_file_free(dvb_file *dvb_file) {
276 	if (dvb_file !is null) {
277 		dvb_entry * entry = dvb_file.first_entry;
278 		dvb_entry * next;
279 		while (entry !is null) {
280 			next = entry.next;
281 			if (entry.channel !is null) { free(entry.channel); }
282 			if (entry.vchannel !is null) { free(entry.vchannel); }
283 			if (entry.location !is null) { free(entry.location); }
284 			if (entry.video_pid !is null) { free(entry.video_pid); }
285 			if (entry.audio_pid !is null) { free(entry.audio_pid); }
286 			if (entry.other_el_pid !is null) { free(entry.other_el_pid); }
287 			if (entry.lnb !is null) { free(entry.lnb); }
288 			free(entry);
289 			entry = next;
290 		}
291 		free(dvb_file);
292 	}
293 }
294 
295 /*
296  * File format description structures defined for the several formats that
297  * the library can read natively.
298  */
299 
300 /**
301  * @brief File format definitions for dvb-apps channel format
302  * @ingroup file
303  */
304 extern __gshared const dvb_parse_file channel_file_format;
305 
306 /**
307  * @brief File format definitions for dvb-apps zap format
308  * @ingroup file
309  */
310 extern __gshared const dvb_parse_file channel_file_zap_format;
311 
312 /*
313  * Prototypes for the several functions defined at dvb-file.c
314  */
315 
316 /**
317  * @brief Read a file at libdvbv5 format
318  * @ingroup file
319  *
320  * @param fname		file name
321  *
322  * @return It returns a pointer to struct dvb_file describing the entries that
323  * were read from the file. If it fails, NULL is returned.
324  */
325 dvb_file* dvb_read_file (const(char)* fname);
326 
327 /**
328  * @brief Write a file at libdvbv5 format
329  * @ingroup file
330  *
331  * @param fname		file name
332  * @param dvb_file	contents of the file to be written
333  *
334  * @return It returns zero if success, or a positive error number if it fails.
335  */
336 int dvb_write_file (const(char)* fname, dvb_file* dvb_file);
337 
338 /**
339  * @brief Read a file on any format natively supported by
340  *			    the library
341  * @ingroup file
342  *
343  * @param fname		file name
344  * @param delsys	Delivery system, as specified by enum fe_delivery_system
345  * @param format	Name of the format to be read
346  *
347  * @return It returns a pointer to struct dvb_file describing the entries that
348  * were read from the file. If it fails, NULL is returned.
349  */
350 dvb_file* dvb_read_file_format (
351     const(char)* fname,
352     uint delsys,
353     dvb_file_formats format);
354 
355 /**
356  * @brief Write a file on any format natively supported by
357  *			    the library
358  * @ingroup file
359  *
360  * @param fname	file name
361  * @param dvb_file	contents of the file to be written
362  * @param delsys	Delivery system, as specified by enum fe_delivery_system
363  * @param format	Name of the format to be read
364  *
365  * @return It a pointer to struct dvb_file on success, NULL otherwise.
366  */
367 int dvb_write_file_format (
368     const(char)* fname,
369     dvb_file* dvb_file,
370     uint delsys,
371     dvb_file_formats format);
372 
373 /**
374  * @brief Stores a key/value pair on a DVB file entry
375  * @ingroup file
376  *
377  * @param entry	entry to be filled
378  * @param cmd	key for the property to be used. It be one of the DVBv5
379  * 		properties, plus the libdvbv5 ones, as defined at dvb-v5-std.h
380  * @param value	value for the property.
381  *
382  * This function seeks for a property with the name specified by cmd and
383  * fills it with value. If the entry doesn't exist, it creates a new key.
384  *
385  * @return Returns 0 if success, or, if the entry has already DTV_MAX_COMMAND
386  * properties, it returns -1.
387  */
388 int dvb_store_entry_prop (dvb_entry* entry, uint cmd, uint value);
389 
390 /**
391  * @brief Retrieves the value associated witha key on a DVB file entry
392  * @ingroup file
393  *
394  * @param entry	entry to be used
395  * @param cmd	key for the property to be found. It be one of the DVBv5
396  * 		properties, plus the libdvbv5 ones, as defined at dvb-v5-std.h
397  * @param value	pointer to store the value associated with the property.
398  *
399  * This function seeks for a property with the name specified by cmd and
400  * fills value with its contents.
401  *
402  * @return Returns 0 if success, or, -1 if the entry doesn't exist.
403  */
404 int dvb_retrieve_entry_prop (dvb_entry* entry, uint cmd, uint* value);
405 
406 /**
407  * @brief stored a new scanned channel into a dvb_file struct
408  * @ingroup file
409  *
410  * @param dvb_file	file struct to be filled
411  * @param parms		struct dvb_v5_fe_parms used by libdvbv5 frontend
412  * @param dvb_desc		struct dvb_desc as described at descriptors.h, filled
413  *			with the descriptors associated with a DVB channel.
414  *			those descriptors can be filled by calling one of the
415  *			scan functions defined at dvb-sat.h.
416  * @param get_detected	if different than zero, uses the frontend parameters
417  *			obtained from the device driver (such as modulation,
418  *			FEC, etc)
419  * @param get_nit		if true, uses the parameters obtained from the MPEG-TS
420  *			NIT table to add newly detected transponders.
421  *
422  * This function should be used to store the services found on a scanned
423  * transponder. Initially, it copies the same parameters used to set the
424  * frontend, that came from a file where the Service ID and Elementary Stream
425  * PIDs are unknown. At tuning time, it is common to set the device to tune
426  * on auto-detection mode (e. g. using QAM/AUTO, for example, to autodetect
427  * the QAM modulation). The libdvbv5's logic will be to check the detected
428  * values. So, the modulation might, for example, have changed to QAM/256.
429  * In such case, if get_detected is 0, it will store QAM/AUTO at the struct.
430  * If get_detected is different than zero, it will store QAM/256.
431  * If get_nit is different than zero, and if the MPEG-TS has info about other
432  * physical channels/transponders, this function will add newer entries to
433  * dvb_file, for it to seek for new transponders. This is very useful especially
434  * for DVB-C, where all transponders belong to the same operator. Knowing one
435  * frequency is generally enough to get all DVB-C transponders.
436  *
437  * @return Returns 0 if success, or, -1 if error.
438  */
439 int dvb_store_channel (
440     dvb_file** dvb_file,
441     dvb_v5_fe_parms* parms,
442     dvb_v5_descriptors* dvb_desc,
443     int get_detected,
444     int get_nit);
445 
446 /**
447  * @brief Ancillary function that seeks for a delivery system
448  * @ingroup file
449  *
450  * @param name	string containing the name of the Delivery System to seek
451  *
452  * If the name is found, this function returns the DVBv5 property that
453  * corresponds to the string given. The function is case-insensitive, and
454  * it can check for alternate ways to write the name of a Delivery System.
455  * Currently, it supports: DVB-C, DVB-H, DVB-S, DVB-S2, DVB-T, DVB-T2,
456  * ISDB-C, ISDB-S, ISDB-T, ATSC-MH, DVBC/ANNEX_A, DVBC/ANNEX_B, DVBT, DSS,
457  * DVBS, DVBS2, DVBH, ISDBT, ISDBS, ISDBC, ATSC, ATSCMH, DTMB, CMMB, DAB,
458  * DVBT2, TURBO, DVBC/ANNEX_C.
459  * Please notice that this doesn't mean that all those standards are properly
460  * supported by the library.
461  *
462  * @return Returns the Delivery System property number if success, -1 if error.
463  */
464 int dvb_parse_delsys (const(char)* name);
465 
466 /**
467  * @brief Ancillary function that parses the name of a file format
468  * @ingroup file
469  *
470  * @param name	string containing the name of the format
471  *		Current valid names are: ZAP, CHANNEL, VDR and DVBV5.
472  *		The name is case-insensitive.
473  *
474  * @return It returns FILE_ZAP, FILE_CHANNEL, FILE_VDR or  FILE_DVBV5
475  * if the name was translated. FILE_UNKNOWN otherwise.
476  */
477 dvb_file_formats dvb_parse_format (const(char)* name);
478 
479 /*
480  * Routines to read a non-libdvbv5 format. They're called by
481  * dvb_read_file_format() or dvb_write_file_format()
482  */
483 
484 /**
485  * @brief Read and parses a one line file format
486  * @ingroup file
487  *
488  * @param fname		file name
489  * @param delsys	delivery system
490  * @param parse_file	pointer struct dvb_parse_file
491  *
492  * @return It a pointer to struct dvb_file on success, NULL otherwise.
493  *
494  * This function is called internally by dvb_read_file_format.
495  */
496 dvb_file* dvb_parse_format_oneline (
497     const(char)* fname,
498     uint delsys,
499     const(dvb_parse_file)* parse_file);
500 
501 /**
502  * @brief Writes a file into an one line file format
503  * @ingroup file
504  *
505  * @param fname		file name
506  * @param dvb_file	contents of the file to be written
507  * @param delsys	delivery system
508  * @param parse_file	pointer struct dvb_parse_file
509  *
510  * @return It returns zero if success, or a positive error number if it fails.
511  *
512  * This function is called internally by dvb_write_file_format.
513  */
514 int dvb_write_format_oneline (
515     const(char)* fname,
516     dvb_file* dvb_file,
517     uint delsys,
518     const(dvb_parse_file)* parse_file);
519 
520 /**
521  * @brief Writes a file into vdr format (compatible up to version 2.1)
522  * @ingroup file
523  *
524  * @param fname		file name
525  * @param dvb_file	contents of the file to be written
526  *
527  * @return It returns zero if success, or a positive error number if it fails.
528  *
529  * This function is called internally by dvb_write_file_format.
530  */
531 int dvb_write_format_vdr (const(char)* fname, dvb_file* dvb_file);
532 
533 // _DVB_FILE_H